home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
- * use is allowed under the terms of the DICE-LICENSE FILE,
- * DICE-LICENSE.TXT.
- */
-
- /*
- * FINAL.C
- *
- * Generate final output
- */
-
- #include "defs.h"
-
- #define HEAD 0x48454144
- #define DBGV 0x44424756
-
- Prototype void GenerateFinalExecutable(FILE *, List *);
- Prototype short ForceSym(Sym *);
-
- void
- GenerateFinalExecutable(fo, list)
- FILE *fo;
- List *list;
- {
- HunkListNode *hl;
- Hunk *hunk;
- int i;
- long nhunk_debug = 0; /* debug hunks */
- long nhunk_symd0 = 0; /* symbol hunks with no associated debug hunks */
- long nhunk_symd1 = 0; /* symbol hunks with associated debug hunks */
- long headdb_seek = 0;
-
- putl(fo, 0x3F3); /* hunk_hdr */
- putl(fo, 0); /* no name */
- putl(fo, NumExtHunks); /* table size */
- putl(fo, 0); /* first hunk */
- putl(fo, NumExtHunks-1);/* last hunk */
-
- for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
- long mask = (hl->HunkId & 0xFFFF0000) & ~HUNKIDF_FLAG;
-
- if (ChipOpt) {
- mask &= ~0x80000000;
- mask |= 0x40000000;
- }
- if (ResOpt)
- putl(fo, mask | (hl->FinalSize >> 2));
- else
- putl(fo, mask | ((hl->FinalSize + hl->AddSize) >> 2));
- }
-
- /*
- * If debugging is enabled (-d), include the master debug hunk
- * required by CPR
- */
-
- if (DebugOpt) {
- long lw = 8 + 3; /* 8 lw of hdr, 3 lw of sub hdr */
- long nsymd0 = 0;
- long nsymd1 = 0;
- long max_array = 0;
-
- for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
- short havesyms = 0;
- short havedebug = 0;
-
- for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
- if (hunk->DbInfo) {
- ++lw; /* number of debug hunks */
- ++nhunk_debug;
- havedebug = 1;
- }
- }
- {
- Sym *sym;
-
- for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
- for (sym = GetHead(&hunk->SymList); sym; sym = GetSucc((Node *)&sym->Node)) {
- if (sym->Type == 1) {
- if (havesyms == 0) {
- if (havedebug)
- ++nhunk_symd1;
- else
- ++nhunk_symd0;
- ++lw;
- havesyms = 1;
- }
- if (havedebug)
- ++nsymd1;
- else
- ++nsymd0;
- }
- }
- }
- }
- }
-
- if ((max_array = nhunk_debug) < nhunk_symd0)
- max_array = nhunk_symd0;
- if (max_array < nhunk_symd1)
- max_array = nhunk_symd1;
-
- putl(fo, 0x3F1);
- putl(fo, lw-2);
- putl(fo, max_array);
- putl(fo, HEAD);
- putl(fo, DBGV);
- putl(fo, 0x30310000);
- putl(fo, nsymd0);
- putl(fo, nsymd1);
- headdb_seek = ftell(fo);
- for (lw = lw - 8; lw; --lw)
- putl(fo, 0);
- }
-
- /*
- * MAIN BODY
- */
-
- for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
- long mask = (hl->HunkId & 0xFFFF0000) & ~HUNKIDF_FLAG;
-
- if (ChipOpt) {
- mask &= ~0x80000000;
- mask |= 0x40000000;
- }
-
- /*
- * output HUNK_CODE, DATA, or BSS
- */
-
- switch(hl->Node.ln_Type) {
- case NT_BSS:
- putl(fo, 0x3EB | mask);
- break;
- case NT_CODE:
- putl(fo, 0x3E9 | mask);
- break;
- case NT_DATA:
- putl(fo, 0x3EA | mask);
- break;
- }
-
- putl(fo, hl->FinalSize >> 2);
-
- /*
- * if not BSS output the code/data
- */
-
- if (hl->Node.ln_Type == NT_DATA || hl->Node.ln_Type == NT_CODE) {
- long n = 0;
-
- for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
- if (hunk->Node.ln_Type == NT_BSS)
- continue;
- fwrite((char *)hunk->Data, 1, hunk->Bytes, fo);
-
- /*
- * Generate jump table
- */
-
- if (hunk->TotalBytes != hunk->Bytes) {
- dbprintf(0, ("WRITE %d bytes of jump table\n", hunk->TotalBytes - hunk->Bytes));
- fwrite((char *)hunk->JmpData, 1, (hunk->TotalBytes - hunk->Bytes + 3) & ~3, fo);
- }
- n += (hunk->TotalBytes + 3) & ~3;
- }
- if (n != hl->FinalSize)
- cerror(EFATAL_FINAL_SIZE_MISMATCH, n, hl->FinalSize);
- }
- #ifdef MINIDICE
- if (ftell(fo) / 23 >= (40000 + 22) / 23)
- cerror(EFATAL_EXECUTABLE_TOO_LARGE);
- #endif
-
- /*
- * If there is any relocation information output that
- */
-
- for (i = 0; i < NumExtHunks; ++i) {
- if (hl->CntReloc32[i])
- break;
- }
- if (i < NumExtHunks) { /* at least one */
- HunkListNode *hl2 = GetHead(list);
-
- if (PIOpt)
- cerror(EERROR_RELOC32_ILLEGAL_PI_NH);
-
- putl(fo, 0x3EC); /* HUNK_RELOC32 */
- for (i = 0; i < NumExtHunks; ++i) {
- long n;
-
- if ((n = hl->CntReloc32[i]) != 0) {
- if (ResOpt && !AbsWordOpt && hl->Node.ln_Type != NT_CODE && hl2->Node.ln_Type != NT_CODE)
- cerror(EERROR_RELOC32_DATA_DATA_RES);
- if (hl->CpyReloc32[i] != n)
- cerror(EFATAL_RELOC_ARRAY_MISMATCH, hl->CpyReloc32[i], n);
-
- putl(fo, n); /* n relocs to */
- putl(fo, i); /* hunk # i */
- fwrite((char *)hl->ExtReloc32[i], 4, n, fo);
- if (PIOpt)
- printf(" 32 bit reloc hunk %ld:$%lx to hunk %d\n", hl->FinalHunkNo, hl->ExtReloc32[i][0], i);
-
- #ifdef DEBUG
- if (DDebug > 5) {
- long j;
- for (j = 0; j < n; ++j)
- printf(" -- reloc h %d offset %08lx\n", i, hl->ExtReloc32[i][j]);
- }
- #endif
- }
- hl2 = GetSucc(&hl2->Node);
- }
- putl(fo, 0);
- }
-
- /*
- * If symbols are enabled dump them
- */
-
- {
- Sym *sym;
-
- for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
- for (sym = GetHead(&hunk->SymList); sym; sym = GetSucc((Node *)&sym->Node)) {
- if (sym->Type == 1 && (SymOpt || (sym->SymLen == 5 && ForceSym(sym))))
- break;
- }
- if (sym)
- break;
- }
- if (hunk) {
- hl->SeekSym = ftell(fo);
- putl(fo, 0x3F0); /* HUNK_SYMBOL */
- for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
- for (sym = GetHead(&hunk->SymList); sym; sym = GetSucc((Node *)&sym->Node)) {
- if (sym->Type == 1 && (SymOpt || (sym->SymLen == 5 && ForceSym(sym)))) {
- long sl = (sym->SymLen + 3) >> 2; /* # lws */
-
- putl(fo, sl);
- fwrite(sym->SymName, 4, sl, fo);
-
- putl(fo, sym->Value + hunk->Offset);
- }
- }
- }
- putl(fo, 0);
- }
- }
-
- /*
- * If debugging is enabled (-d), include that
- */
-
- if (DebugOpt) {
- for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
- DBInfo *dbinfo;
-
- if ((dbinfo = hunk->DbInfo) == NULL)
- continue;
- dbinfo->di_Base = ToMsbOrder(hunk->Offset);
- hunk->SeekDebug = ftell(fo);
- fwrite(dbinfo, 4, dbinfo->di_Size + 2, fo);
- }
- }
-
- /*
- * HUNK_END
- */
-
- putl(fo, 0x3F2);
- }
-
- /*
- * DEBUG MASTER HEADER (CPR SUPPORT)
- */
-
- if (DebugOpt) {
- fseek(fo, headdb_seek, 0);
-
- putl(fo, nhunk_debug);
- for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
- for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
- if (hunk->DbInfo)
- putl(fo, (hl->FinalHunkNo << 24) | hunk->SeekDebug);
- }
- }
-
- putl(fo, nhunk_symd0);
- if (SymOpt) {
- for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
- short havedebug = 0;
- for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
- if (hunk->DbInfo) {
- havedebug = 1;
- break;
- }
- }
- if (hl->SeekSym && havedebug == 0) {
- putl(fo, (hl->FinalHunkNo << 24) | hl->SeekSym);
- }
- }
- }
-
- putl(fo, nhunk_symd1);
-
- if (SymOpt) {
- for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
- short havedebug = 0;
- for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
- if (hunk->DbInfo) {
- havedebug = 1;
- break;
- }
- }
- if (hl->SeekSym && havedebug == 1) {
- putl(fo, (hl->FinalHunkNo << 24) | hl->SeekSym);
- }
- }
- }
-
- fseek(fo, 0L, 2);
- }
- }
-
- /*
- * Force _main, @main, _exit, @exit
- *
- */
-
- short
- ForceSym(sym)
- Sym *sym;
- {
- /*if (sym->SymLen == 5)*/ {
- if (strncmp(sym->SymName + 1, "main", 4) == 0)
- return(1);
- if (strncmp(sym->SymName + 1, "exit", 4) == 0)
- return(1);
- }
- return(0);
- }
-
-